import isEmpty from 'lodash/isEmpty'
import isString from 'lodash/isString'
import isFunction from 'lodash/isFunction'

const LANGAGE_DEF = 'zh-CN'

export const SDP_UC = 'sdp.uc'
export const SDP_SYS = 'sdp.sys'
export const SDP_APPFAC = 'sdp.appfactory'

const RUNTIME_WEAPP = 'miniprogram'
const MACHINE_IOS = 'iOS'
const MACHINE_ANDROID = 'Android'
const WEBVIEW_SMARTCAN = 'SmartCanWebView'

declare global {
  interface Window {
    bridgeReady: () => void
    Bridge: any
    __wxjs_environment: string
  }
}

/**
 * Bridge注入回调
 *
 * @param {function} func
 */
export const bridgeReady = (func): void => {
  if (isFunction(func) && window) {
    window.bridgeReady = () => {
      func()
    }
  }
}

/**
 * Bridge能力是否存在
 */
export const bridgeExist = (name: string): boolean => {
  if (window.Bridge) {
    try {
      return window.Bridge.require(name) != null
    } catch (e) {
      console.error(e)
    }
  }
  return false
}

/**
 * Bridge能力申请方法
 */
export const bridgeRequire = (name: string) => {
  if (window.Bridge) {
    try {
      return window.Bridge.require(name).promise()
    } catch (e) {
      console.error(e)
    }
  }
  return null
}

/**
 * 跳转指定页面
 *
 * @param {object} page
 * @returns {boolean}
 */
export const goPage = async (page): Promise<boolean> => {
  if (page != null) {
    const require = bridgeRequire(SDP_APPFAC)
    if (require != null) {
      let jumper
      try {
        jumper = await require.goPage(page)
      } catch (e) {
        console.error(e)
      }
      if (!isEmpty(jumper)) {
        if (jumper.result) {
          return true
        } else {
          console.error(jumper.message)
        }
      }
    }
  }
  return false
}

/**
 * 是否iOS系统
 *
 * @returns {boolean}
 */
export const isIOS = async (): Promise<boolean> => {
  return _verifyPlatform(MACHINE_IOS)
}

/**
 * 是否Android系统
 */
export const isAndroid = async (): Promise<boolean> => {
  return _verifyPlatform(MACHINE_ANDROID)
}

/**
 * 是否访客访问
 */
export const isGuest = async (): Promise<boolean> => {
  const require = bridgeRequire(SDP_UC)
  if (require != null) {
    let guest
    try {
      guest = await require.isGuest()
    } catch (e) {
      console.error(e)
    }
    return guest === 1
  }
  return true
}

/**
 * 是否运行在微信小程序环境
 */
export const isWeapp = (): boolean => {
  return window.__wxjs_environment === RUNTIME_WEAPP || (
    window.navigator ? new RegExp(RUNTIME_WEAPP, 'i').test(navigator.userAgent) : false
  )
}

/**
 * 是否运行在应用工厂提供的WebView
 *
 * @returns {boolean}
 */
export const isSmartCanWebView = () => {
  return window.navigator ? new RegExp(WEBVIEW_SMARTCAN, 'i').test(navigator.userAgent) : false
}

/**
 * 应用返回键绑定事件
 *
 * @param {function} func
 */
export const takeKeyBack = (func): void => {
  if (isFunction(func) && window.Bridge) {
    window.Bridge.__isTakeKeyBack = func
  }
}

/**
 * 显示应用导航栏
 */
export const showNavBar = async (): Promise<void> => {
  _toggleNavBar({
    display: true
  })
}

/**
 * 隐藏应用导航栏
 */
export const hideNavBar = async (): Promise<void> => {
  _toggleNavBar({
    display: false
  })
}

/**
 * 显示应用导航栏菜单
 *
 * @param  {...string} menu
 */
export const showNavBarMenu = async (...menu): Promise<void> => {
  if (!isEmpty(menu)) {
    const cfg = {}
    for (let key, i = 0, l = menu.length; i < l; i++) {
      key = menu[i]
      if (isString(key)) {
        cfg[key] = true
      }
    }
    _toggleNavBarMenu(cfg)
  }
}

/**
 * 隐藏应用导航栏菜单
 *
 * @param  {...string} menu
 */
export const hideNavBarMenu = async (...menu): Promise<void> => {
  if (!isEmpty(menu)) {
    const cfg = {}
    for (let key, i = 0, l = menu.length; i < l; i++) {
      key = menu[i]
      if (isString(key)) {
        cfg[key] = false
      }
    }
    _toggleNavBarMenu(cfg)
  }
}

/**
 * 注册应用导航栏菜单
 *
 * @param {object} menu
 */
export const registNavBarMenu = async (menu): Promise<void> => {
  if (menu != null) {
    const require = bridgeRequire(SDP_APPFAC)
    if (require != null) {
      try {
        await require.registerWebviewMenu(menu)
      } catch (e) {
        console.error(e)
      }
    }
  }
}

/**
 * 移除应用导航栏菜单
 *
 * @param {object} menu
 */
export const removeNavBarMenu = async (menu): Promise<void> => {
  if (menu != null) {
    const require = bridgeRequire(SDP_APPFAC)
    if (require != null) {
      try {
        await require.unRegisterWebviewMenu(menu)
      } catch (e) {
        console.error(e)
      }
    }
  }
}

/**
 * 获得用户MAC信息
 * {url, method}
 *
 * @param {object} path
 * @returns {string}
 */
export const getMACContent = async (path): Promise<void|null> => {
  if (path != null) {
    const require = bridgeRequire(SDP_UC)
    if (require != null) {
      let secret
      try {
        secret = await require.getMACContent(path)
      } catch (e) {
        console.error(e)
      }
      if (!isEmpty(secret)) {
        if (secret.result) {
          return secret.returnMessage
        } else {
          console.error(secret.message)
        }
      }
    }
  }
  return null
}

/**
 * 获得应用语言类型
 *
 * @returns {string}
 */
export const getLanguageType = async (): Promise<string> => {
  const require = bridgeRequire(SDP_APPFAC)
  if (require != null) {
    try {
      return await require.getLanguageType()
    } catch (e) {
      console.error(e)
    }
  }
  return LANGAGE_DEF
}

/**
 * 结束应用当前页面
 */
export const finishCurrentPage = async (): Promise<void> => {
  const require = bridgeRequire(SDP_APPFAC)
  if (require != null) {
    try {
      await require.finishCurrentPage()
    } catch (e) {
      console.error(e)
    }
  }
}

/**
 * 获得系统剪贴板内容
 *
 */
export const getClipboardValue = async (): Promise<string> => {
  const require = bridgeRequire(SDP_APPFAC)
  if (require != null) {
    try {
      return await require.getClipboardValue()
    } catch (e) {
      console.error(e)
    }
  }
  return ''
}

const _toggleNavBar = async (display): Promise<void> => {
  const require = bridgeRequire(SDP_APPFAC)
  if (require != null) {
    try {
      await require.navigationBar(display)
    } catch (e) {
      console.error(e)
    }
  }
}

const _toggleNavBarMenu = async (display): Promise<void> => {
  const require = bridgeRequire(SDP_APPFAC)
  if (require != null) {
    try {
      await require.setMenuVisible(display)
    } catch (e) {
      console.error(e)
    }
  }
}

const _verifyPlatform = async (machine): Promise<boolean> => {
  const require = bridgeRequire(SDP_SYS)
  if (require != null) {
    let platform
    try {
      platform = await require.getPlatform()
    } catch (e) {
      console.error(e)
    }
    return platform === machine
  }
  return false
}
